home *** CD-ROM | disk | FTP | other *** search
/ Acorn User: China / Acorn User China CD-ROM (UK) (Disc A) / Acorn User China CD-ROM (UK) (Disc A).bin / DEMON / MISC / NETLITE2.ARC / NET / c / VT100 < prev    next >
Encoding:
Text File  |  1993-04-12  |  36.9 KB  |  848 lines

  1. /* cu-notic.txt         NCSA Telnet version 2.2C     2/3/89
  2.    Notice:
  3.         Portions of this file have been modified by
  4.         The Educational Resources Center of Clarkson University.
  5.  
  6.         All modifications made by Clarkson University are hereby placed
  7.         in the public domain, provided the following statement remain in
  8.         all source files.
  9.  
  10.         "Portions Developed by the Educational Resources Center, 
  11.                 Clarkson University"
  12.  
  13.         Bugs and comments to bkc@omnigate.clarkson.edu
  14.                                 bkc@clgw.bitnet
  15.  
  16.         Brad Clements
  17.         Educational Resources Center
  18.         Clarkson University
  19. */
  20.  
  21. /*
  22.  *
  23.  *      Virtual Screen Kernel Emulation Routines
  24.  *                      (vsem.c)
  25.  *  
  26.  *   National Center for Supercomputing Applications
  27.  *      by Gaige B. Paulsen
  28.  *
  29.  *    This file contains the private emulation calls for the NCSA
  30.  *  Virtual Screen Kernel.
  31.  *
  32.  *      Version Date    Notes
  33.  *      ------- ------  ---------------------------------------------------
  34.  *      0.01    861102  Initial coding -GBP
  35.  *      0.10    861111  Added/Modified VT emulator -GBP
  36.  *      0.50    861113  First compiled edition -GBP
  37.  *              2.1     871130  NCSA Telnet 2.1 -GBP
  38.  *              2.2     880715  NCSA Telnet 2.2 -GBP
  39.  */
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include "sprite.h"
  44. #include "os.h"
  45. #include "bbc.h"
  46. #include "menu.h"
  47. #include "wimp.h"
  48. #include "wimpt.h"
  49. #include "os.h"
  50. #include "global.h"
  51. #include "misc.h"
  52. #include "window.h"
  53. #include "session.h"
  54.  
  55. #define OS_ChangedBox  0x0000005a
  56.  
  57. typedef struct
  58. {
  59.         int flag;
  60.         wimp_box box;
  61. }
  62. change_box;
  63.            
  64. static void Control_Chars(struct Window_Struct *, char);
  65. static void Window_Scroll(struct Window_Struct *);
  66. static os_error *Changed_Box(int, change_box **);
  67. static int keyscan(int);
  68.  
  69. #define XtoWork(x) ((x) << 1)
  70. #define YtoWork(y) ((y) << 2)
  71.  
  72. void Window_Write(void *w, char *s, int n)
  73. {
  74.         struct Window_Struct *Window = (struct Window_Struct *)w;
  75.         sprite_state State;
  76.         wimp_redrawstr r;
  77.         register int Escflg;
  78.         change_box *Box; 
  79.         int i, cx, cy;
  80.  
  81.         if (Window->Record != NULL) fwrite(s, 1, n, Window->Record);
  82.  
  83.         sprite_outputtosprite(Window->Sprite.Area, &Window->Sprite.id, Window->Save_Area, &State);
  84.  
  85.         Changed_Box(1, &Box);
  86.         Changed_Box(2, &Box);
  87.  
  88.         Escflg = Window->Esc_Flag;
  89.  
  90.         if (Window->Cursor)
  91.         {
  92.                 cx = Window->x * 16;
  93.                 cy = 768 - Window->y * 32 - 28;
  94.                 bbc_vduq(25, 4,   cx % 256, cx / 256,
  95.                                   cy % 256, cy / 256);
  96.                 bbc_vduq(25, 102, (cx + 16) % 256, (cx + 16) / 256,
  97.                                   (cy + 24) % 256, (cy + 24) / 256);
  98.         }
  99.  
  100.         bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  101.         bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  102.  
  103.         while (n > 0)
  104.         {
  105.                 while (Escflg == ESCAPE_NONE && n > 0 && *s < 32)
  106.                 {
  107.                         switch (*s)
  108.                         {
  109.                                 case 0x1b:      /* \E ... */
  110.                                         Escflg = ESCAPE_FOUND;
  111.                                         break;
  112.                                 default:
  113.                                         Control_Chars(Window, *s);
  114.                                         break;
  115.                         }
  116.  
  117.                         s++;
  118.                         n--;
  119.                 }
  120.  
  121.                 bbc_vduq(17, 128 + Window->Background[Window->Attr]);
  122.                 bbc_vduq(17,       Window->Foreground[Window->Attr]);
  123.  
  124.                 while (n > 0 && Escflg == ESCAPE_NONE && *s >= 32)
  125.                 {
  126.                         if ((Window->Charset == CHARSET_G0 && Window->G0 == FONT_GRAPH) ||
  127.                             (Window->Charset == CHARSET_G1 && Window->G1 == FONT_GRAPH))
  128.                         {
  129.                                 bbc_vdu((*s >= 0x60) ? *s + 128 : *s);
  130.                         }
  131.                         else
  132.                         {
  133.                                 bbc_vdu(*s);
  134.                         }
  135.  
  136.                         Window->x++;
  137.                         Window_Scroll(Window);
  138.  
  139.                         s++;
  140.                         n--;
  141.                 }
  142.  
  143.                 bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  144.                 bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  145.  
  146.                 while (n > 0 && Escflg == ESCAPE_FOUND)
  147.                 {
  148.                         switch (*s)
  149.                         {
  150.                                 case '[':       /* \E[ ... */
  151.                                         Window->Parmptr = 0;
  152.                                         for (i = 0; i < 6; i++)
  153.                                                  Window->Parms[i] = -1;
  154.                                         Escflg = ESCAPE_1;
  155.                                         break;
  156.                                 case '7':       /* \E7 - sc */
  157.                                         Window->Save_x    = Window->x;
  158.                                         Window->Save_y    = Window->y;
  159.                                         Window->Save_Attr = Window->Attr;
  160.                                         Escflg = ESCAPE_NONE;
  161.                                         break;
  162.                                 case '8':       /* \E8 - rc */
  163.                                         Window->x    = Window->Save_x;
  164.                                         Window->y    = Window->Save_y;
  165.                                         Window->Attr = Window->Save_Attr;
  166.                                         Escflg = ESCAPE_NONE;
  167.                                         break;
  168.                                 case 'c':       /* \Ec ... */
  169.                                         Window_Reset(Window);
  170.                                         Escflg = ESCAPE_NONE;
  171.                                         break;
  172.                                 case 'D':       /* \ED */
  173.                                         Window->y++;
  174.                                         Window_Scroll(Window);
  175.                                         Escflg = ESCAPE_NONE;
  176.                                         break;
  177.                                 case 'E':       /* \EE */
  178.                                         Window->y++;
  179.                                         Window->x = 0;
  180.                                         Window_Scroll(Window);
  181.                                         Escflg = ESCAPE_NONE;
  182.                                         break;
  183.                                 case 'M':       /* \EM - ri */
  184.                                         Window->y--;
  185.                                         Window_Scroll(Window);
  186.                                         Escflg = ESCAPE_NONE;
  187.                                         break;
  188.                                 case '>':       /* \E> - rmkx */
  189.                                         Window->Session->keypad = 0;
  190.                                         Escflg = ESCAPE_NONE;
  191.                                         break;
  192.                                 case '=':       /* \E= - smkx */
  193.                                         Window->Session->keypad = 1;
  194.                                         Escflg = ESCAPE_NONE;
  195.                                         break;
  196.                                 case '(':       /* \E( ... */
  197.                                         Escflg = ESCAPE_3;
  198.                                         break;
  199.                                 case ')':       /* \E) ... */
  200.                                         Escflg = ESCAPE_4;
  201.                                         break;
  202.                                 case '#':       /* \E# ... */
  203.                                         Escflg = ESCAPE_5;
  204.                                         break;
  205.                                 case 'H':       /* \EH - hts */
  206.                                         Window->Tabs[Window->x] = 'x';
  207.                                         Escflg = ESCAPE_NONE;
  208.                                         break;
  209.                                 default:
  210.                                         if (*s < 32)
  211.                                                Control_Chars(Window, *s);
  212.                                         else
  213.                                                Escflg = ESCAPE_NONE;
  214.                                         break;
  215.                         }
  216.  
  217.                         s++;
  218.                         n--;
  219.                 }
  220.  
  221.                 while (Escflg == ESCAPE_1 && n > 0)
  222.                 {
  223.                         switch (*s)
  224.                         {
  225.                                 case '0':
  226.                                 case '1':
  227.                                 case '2':
  228.                                 case '3':
  229.                                 case '4':
  230.                                 case '5':
  231.                                 case '6':
  232.                                 case '7':
  233.                                 case '8':
  234.                                 case '9':
  235.                                         if (Window->Parms[Window->Parmptr] < 0) Window->Parms[Window->Parmptr] = 0;
  236.                                         Window->Parms[Window->Parmptr] *= 10;
  237.                                         Window->Parms[Window->Parmptr] += *s - '0';
  238.                                         break;
  239.                                 case '?':       /* \E[? ... */
  240.                                         Window->Parms[Window->Parmptr++] = -2;
  241.                                         break;
  242.                                 case ';':       /* \E[nn; ... */
  243.                                         Window->Parmptr++;
  244.                                         break;
  245.                                 case 'A':       /* \E[%p1%dA - cuu, cuu1 */
  246.                                         if (Window->Parms[0] < 1)
  247.                                                Window->y--;
  248.                                         else
  249.                                                Window->y -= Window->Parms[0];
  250.                                         Window_Scroll(Window);
  251.                                         Escflg = ESCAPE_NONE;
  252.                                         break;
  253.                                 case 'B':       /* \E[%p1%dB - cud */
  254.                                         if (Window->Parms[0] < 1)
  255.                                                Window->y++;
  256.                                         else
  257.                                                Window->y += Window->Parms[0];
  258.                                         Window_Scroll(Window);
  259.                                         Escflg = ESCAPE_NONE;
  260.                                         break;
  261.                                 case 'C':       /* \E[%p1%dC - cuf, cuf1 */
  262.                                         if (Window->Parms[0] < 1)
  263.                                                Window->x++;
  264.                                         else
  265.                                                Window->x += Window->Parms[0];
  266.                                         Window_Scroll(Window);
  267.                                         Escflg = ESCAPE_NONE;
  268.                                         break;
  269.                                 case 'D':       /* \E[%p1%dD - cub, cub1 */
  270.                                         if (Window->Parms[0] < 1)
  271.                                                Window->x--;
  272.                                         else
  273.                                                Window->x -= Window->Parms[0];
  274.                                         Window_Scroll(Window);
  275.                                         Escflg = ESCAPE_NONE;
  276.                                         break;
  277.                                 case 'f':       /* \E[%i%p1%d;%p2%df */
  278.                                 case 'H':       /* \E[%i%p1%d;%p2%dH - cup */
  279.                                         Window->x = Window->Parms[1] - 1;
  280.                                         Window->y = Window->Parms[0] - 1;
  281.                                         if (Window->x < 0)  Window->x = 0;
  282.                                         if (Window->x > 79) Window->x = 79;
  283.                                         if (Window->y < Window->Top)    Window->y = Window->Top;
  284.                                         if (Window->y > Window->Bottom) Window->y = Window->Bottom;
  285.                                         bbc_vduq(31, Window->x, Window->y);
  286.                                         Escflg = ESCAPE_NONE;
  287.                                         break;
  288.                                 case 'K':       /* \E[K - e1*/
  289.                                         switch (Window->Parms[0])
  290.                                         {
  291.                                                 case -1:
  292.                                                 case  0:
  293.                                                         bbc_vduq(23,8,5,6,0,0,0,0,0,0);
  294.                                                         break;
  295.                                                 case  1:
  296.                                                         bbc_vduq(23,8,4,5,0,0,0,0,0,0);
  297.                                                         break;
  298.                                                 case  2:
  299.                                                         bbc_vduq(23,8,4,6,0,0,0,0,0,0);
  300.                                                         break;
  301.                                                 default:
  302.                                                         Escflg = ESCAPE_NONE;
  303.                                                         break;
  304.                                         }
  305.                                         Escflg = ESCAPE_NONE;
  306.                                         break;
  307.                                 case 'J':       /* \E[J - ed */
  308.                                         switch (Window->Parms[0])
  309.                                         {
  310.                                                 case -1:
  311.                                                 case  0:
  312.                                                         bbc_vduq(23,8,5,10,0,0,0,0,0,0);
  313.                                                         break;
  314.                                                 case  1:
  315.                                                         bbc_vduq(23,8,0,5,0,0,0,0,0,0);
  316.                                                         break;
  317.                                                 case  2:
  318.                                                         bbc_vduq(23,8,0,10,0,0,0,0,0,0);
  319.                                                         break;
  320.                                                 default:
  321.                                                         Escflg = ESCAPE_NONE;
  322.                                                         break;
  323.                                         }
  324.                                         Escflg = ESCAPE_NONE;
  325.                                         break;
  326.                                 case 'm':       /* \E[nnm - smso, rmso, smul, */
  327.                                                 /*     rmul, bold, rev, blink */
  328.                                         switch (Window->Parms[0])
  329.                                         {
  330.                                                 case -1:
  331.                                                 case 0:         /* \E[0m - rmso, rmul */
  332.                                                         Window->Attr = ATTR_NORMAL;
  333.                                                         break;
  334.                                                 case 1:         /* \E[1m - bold */
  335.                                                         Window->Attr = ATTR_BOLD;
  336.                                                         break;
  337.                                                 case 4:         /* \E[4m - smul */
  338.                                                         Window->Attr = ATTR_UNDER;
  339.                                                         break;
  340.                                                 case 5:         /* \E[5m - blink */
  341.                                                         Window->Attr = ATTR_BLINK;
  342.                                                         break;
  343.                                                 case 7:         /* \E[7m - smso, rev */
  344.                                                         Window->Attr = ATTR_REVERSE;
  345.                                                         break;
  346.                                                 default:
  347.                                                         break;
  348.                                         }
  349.                                         Escflg = ESCAPE_NONE;
  350.                                         break;
  351.                                 case 'L':       /* \E[L - il1 */
  352.                                         if (Window->Parms[0] < 1) Window->Parms[0] = 1;
  353.                                         bbc_vduq(28, 0, Window->Bottom, 79, Window->y);
  354.                                         for (i = 0; i < Window->Parms[0]; i++)
  355.                                                  bbc_vduq(23,7,0,2,0,0,0,0,0,0); 
  356.                                         bbc_vduq(28,0,Window->Bottom,79,Window->Top);
  357.                                         bbc_vduq(31, Window->x, Window->y);
  358.                                         Escflg = ESCAPE_NONE;
  359.                                         break;
  360.                                 case 'M':       /* \E[M - dl1 */
  361.                                         if (Window->Parms[0] < 1) Window->Parms[0] = 1;                                                
  362.                                         bbc_vduq(28, 0, Window->Bottom, 79, Window->y);
  363.                                         for (i = 0; i < Window->Parms[0]; i++)
  364.                                                  bbc_vduq(23,7,0,3,0,0,0,0,0,0); 
  365.                                         bbc_vduq(28, 0, Window->Bottom, 79, Window->Top);
  366.                                         bbc_vduq(31, Window->x, Window->y);
  367.                                         Escflg = ESCAPE_NONE;
  368.                                         break;
  369.                                 case 'P':       /* \E[P */
  370.                                         if (Window->Parms[0] < 1) Window->Parms[0] = 1;
  371.                                         bbc_vduq(28, Window->x, Window->y, 79, Window->y);
  372.                                         for (i = 0; i < Window->Parms[0]; i++)
  373.                                                  bbc_vduq(23,7,0,1,0,0,0,0,0,0); 
  374.                                         bbc_vduq(28, 0, Window->Bottom, 79, Window->Top);
  375.                                         bbc_vduq(31, Window->x, Window->y);
  376.                                         Escflg = ESCAPE_NONE;
  377.                                         break;
  378.                                 case 'r':       /* \E[r */
  379.                                         if (Window->Parms[0] < 0)
  380.                                                 Window->Top = 0;
  381.                                         else
  382.                                                 Window->Top = Window->Parms[0] - 1;
  383.                                         if (Window->Parms[1] < 0)
  384.                                                 Window->Bottom = 23;
  385.                                         else
  386.                                                 Window->Bottom = Window->Parms[1] - 1;
  387.                                         if (Window->Top < 0)  Window->Top = 0;
  388.                                         if (Window->Top > 22) Window->Top = 22;
  389.                                         if (Window->Bottom < 1)  Window->Bottom = 23;
  390.                                         if (Window->Bottom > 23) Window->Bottom = 23;
  391.                                         Window->x = 0;
  392.                                         Window->y = Window->Top;
  393.                                         bbc_vduq(28, 0, Window->Bottom , 79, Window->Top);
  394.                                         bbc_vduq(31, Window->x, Window->y);
  395.                                         Escflg = ESCAPE_NONE;
  396.                                         break;
  397.                                 case 'h':       /* \E[h - cnorm, cvvis */
  398.                                         Window->Cursor = 1;
  399.                                         Escflg = ESCAPE_NONE;
  400.                                         break;
  401.                                 case 'l':       /* \E[l - civis */
  402.                                         Window->Cursor = 0;
  403.                                         Escflg = ESCAPE_NONE;
  404.                                         break;
  405.                                 case 'g':       /* \E[g - tbc */
  406.                                         if (Window->Parms[0] == 3)
  407.                                         {
  408.                                                 for (i = 0; i < SCREEN_WIDTH; i++)
  409.                                                         Window->Tabs[i] = ' ';
  410.                                         }
  411.                                         else
  412.                                         {
  413.                                                 if (Window->Parms[0] == 0 || Window->Parms[0] < 0)
  414.                                                         Window->Tabs[Window->x] = ' ';
  415.                                         }
  416.                                         Escflg = ESCAPE_NONE;
  417.                                         break;
  418.                                 default:
  419.                                         if (*s < 32)
  420.                                                 Control_Chars(Window, *s);
  421.                                         else
  422.                                                 Escflg = ESCAPE_NONE;
  423.                                         break;
  424.                         }
  425.  
  426.                         s++;
  427.                         n--;
  428.                 }
  429.  
  430.                 while (Escflg == ESCAPE_3 && n > 0)
  431.                 {
  432.                         switch (*s)
  433.                         {
  434.                                 case 'A':       /* \E(A */
  435.                                 case 'B':       /* \E(B - font0 */
  436.                                 case '1':       /* \E(1 */
  437.                                         Window->G0 = FONT_ASCII;
  438.                                         Escflg = ESCAPE_NONE;
  439.                                         break;
  440.                                 case '0':       /* \E(0 - font1 */
  441.                                 case '2':       /* \E(2 */
  442.                                         Window->G0 = FONT_GRAPH;
  443.                                         Escflg = ESCAPE_NONE;
  444.                                         break;
  445.                                 default:
  446.                                         if (*s < 32)
  447.                                                 Control_Chars(Window, *s);
  448.                                         else
  449.                                                 Escflg = ESCAPE_NONE;
  450.                                         break;
  451.                         }
  452.  
  453.                         s++;
  454.                         n--;
  455.                 }
  456.  
  457.                 while (Escflg == ESCAPE_4 && n > 0)
  458.                 {
  459.                         switch (*s)
  460.                         {
  461.                                 case 'A':       /* \E)A */
  462.                                 case 'B':       /* \E)B */
  463.                                 case '1':       /* \E)1 */
  464.                                         Window->G1 = FONT_ASCII;
  465.                                         Escflg = ESCAPE_NONE;
  466.                                         break;
  467.                                 case '0':       /* \E)0 */
  468.                                 case '2':       /* \E)2 */
  469.                                         Window->G1 = FONT_GRAPH;
  470.                                         Escflg = ESCAPE_NONE;
  471.                                         break;
  472.                                 default:
  473.                                         if (*s < 32)
  474.                                                 Control_Chars(Window, *s);
  475.                                         else
  476.                                                 Escflg = ESCAPE_NONE;
  477.                                         break;
  478.                         }
  479.  
  480.                         s++;
  481.                         n--;
  482.                 }
  483.  
  484.                 while (Escflg == ESCAPE_5 && n > 0)
  485.                 {
  486.                         if (*s < 32)
  487.                                 Control_Chars(Window, *s);
  488.                         else
  489.                                 Escflg = ESCAPE_NONE;
  490.  
  491.                         s++;
  492.                         n--;
  493.                 }
  494. /*
  495.                 if (Escflg > ESCAPE_1 && n > 0)
  496.                 {
  497.                         Escflg = ESCAPE_NONE;
  498.                         s++;
  499.                         n--;
  500.                 }
  501. */
  502.         }
  503.  
  504.         Window->Esc_Flag = Escflg;
  505.  
  506.         if (Window->Cursor)
  507.         {
  508.                 cx = Window->x * 16;
  509.                 cy = 768 - Window->y * 32 - 28;
  510.                 bbc_vduq(25, 4,   cx % 256, cx / 256,
  511.                                   cy % 256, cy / 256);
  512.                 bbc_vduq(25, 102, (cx + 16) % 256, (cx + 16) / 256,
  513.                                   (cy + 24) % 256, (cy + 24) / 256);
  514.         }
  515.  
  516.         Changed_Box(-1, &Box);
  517.  
  518.         r.w = Window->Window_Handle;
  519.         r.box.x0 = XtoWork(Box->box.x0) * Window->X_Mag_Mult / Window->X_Div_Mult - XtoWork(1);
  520.         r.box.x1 = XtoWork(Box->box.x1) * Window->X_Mag_Mult / Window->X_Div_Mult + XtoWork(1);
  521.         r.box.y0 = YtoWork(Box->box.y0 - SPRITE_HEIGHT) * Window->Y_Mag_Mult / Window->Y_Div_Mult - YtoWork(1);
  522.         r.box.y1 = YtoWork(Box->box.y1 - SPRITE_HEIGHT) * Window->Y_Mag_Mult / Window->Y_Div_Mult + YtoWork(1);
  523.  
  524.         sprite_restorestate(State);
  525.  
  526.         Update_Window(Window, r);
  527. }
  528.  
  529. static void Control_Chars(struct Window_Struct *Window, char c)
  530. {
  531.         int i;
  532.  
  533.         switch (c)
  534.         {
  535.                 case 0x07:      /* ^G - bel */
  536.                         bbc_vdu(7);
  537.                         break;
  538.                 case 0x08:      /* ^H - cub1 */
  539.                         Window->x--;
  540.                         Window_Scroll(Window);
  541.                         break;
  542.                 case 0x0e:
  543.                         Window->Charset = CHARSET_G1;
  544.                         break;
  545.                 case 0x0f:
  546.                         Window->Charset = CHARSET_G0;
  547.                         break;
  548.                 case 0x09:      /* ^I - ht */
  549.                         for (i = Window->x + 1; i < SCREEN_WIDTH; i++)
  550.                         {      
  551.                                   if (Window->Tabs[i] == 'x')
  552.                                   {
  553.                                          Window->x = i;
  554.                                          break;
  555.                                   }
  556.                         }
  557.                         Window_Scroll(Window);
  558.                         break;
  559.                 case 0x0d:      /* ^M - cr */
  560.                         Window->x = 0;
  561.                         bbc_vdu(13);
  562.                         break;
  563.                 case 0x0a:      /* ^J - lf */
  564.                         Window->y++;
  565.                         Window->x = 0;
  566.                         if (Window->y > Window->Bottom)
  567.                                 Window->y = Window->Bottom;
  568.                         bbc_vdu(10);
  569.                         bbc_vdu(13);
  570.                         break;
  571.                 default:
  572.                         break;
  573.         }
  574. }
  575.  
  576. /* TTY input driver */
  577. int keymap(int raw, int keypad, char *buffer, int c)
  578. {
  579.         if (raw)
  580.         {
  581.                  if (keypad)
  582.                  {
  583.                          if (keyscan(106))
  584.                          {
  585.                                  strcpy(buffer, "\033Op");
  586.                                  return(3);
  587.                          }
  588.                          if (keyscan(107))
  589.                          {
  590.                                  strcpy(buffer, "\033Oq");
  591.                                  return(3);
  592.                          }
  593.                          if (keyscan(124))
  594.                          {
  595.                                  strcpy(buffer, "\033Or");
  596.                                  return(3);
  597.                          }
  598.                          if (keyscan(108))
  599.                          {
  600.                                  strcpy(buffer, "\033Os");
  601.                                  return(3);
  602.                          }
  603.                          if (keyscan(122))
  604.                          {
  605.                                  strcpy(buffer, "\033Ot");
  606.                                  return(3);
  607.                          }
  608.                          if (keyscan(123))
  609.                          {
  610.                                  strcpy(buffer, "\033Ou");
  611.                                  return(3);
  612.                          }
  613.                          if (keyscan(26))
  614.                          {
  615.                                  strcpy(buffer, "\033Ov");
  616.                                  return(3);
  617.                          }
  618.                          if (keyscan(27))
  619.                          {
  620.                                  strcpy(buffer, "\033Ow");
  621.                                  return(3);
  622.                          }
  623.                          if (keyscan(42))
  624.                          {
  625.                                  strcpy(buffer, "\033Ox");
  626.                                  return(3);
  627.                          }
  628.                          if (keyscan(43))
  629.                          {
  630.                                  strcpy(buffer, "\033Oy");
  631.                                  return(3);
  632.                          }
  633.                          if (keyscan(59))
  634.                          {
  635.                                  strcpy(buffer, "\033Om");
  636.                                  return(3);
  637.                          }
  638.                          if (keyscan(58))
  639.                          {
  640.                                  strcpy(buffer, "\033Ol");
  641.                                  return(3);
  642.                          }
  643.                          if (keyscan(76))
  644.                          {
  645.                                  strcpy(buffer, "\033On");
  646.                                  return(3);
  647.                          }
  648.                          if (keyscan(60))
  649.                          {
  650.                                  strcpy(buffer, "\033OM");
  651.                                  return(3);
  652.                          }
  653.                  }
  654.  
  655.                  switch (c)
  656.                  {
  657.                          case 0x181:   /* F1 */
  658.                                strcpy(buffer, "\033OP");
  659.                                return(3);
  660.                          case 0x182:   /* F2 */
  661.                                strcpy(buffer, "\033OQ");
  662.                                return(3);
  663.                          case 0x183:   /* F3 */
  664.                                strcpy(buffer, "\033OR");
  665.                                return(3);
  666.                          case 0x184:   /* F4 */
  667.                                strcpy(buffer, "\033OS");
  668.                                return(3);
  669.                          case 0x1CD:   /* Insert */
  670.                                strcpy(buffer, "\033[1~");
  671.                                return(4);
  672.                          case 0x1E:    /* Home */
  673.                                strcpy(buffer, "\033[2~");
  674.                                return(4);
  675.                          case 0x19F:   /* Page Up */
  676.                                strcpy(buffer, "\033[3~");
  677.                                return(4);
  678.                          case 0x7F:    /* Delete */
  679.                                strcpy(buffer, "\033[4~");
  680.                                return(4);
  681.                          case 0x18B:   /* Copy */
  682.                                strcpy(buffer, "\033[5~");
  683.                                return(4);
  684.                          case 0x19E:   /* Page Down */
  685.                                strcpy(buffer, "\033[6~");
  686.                                return(4);
  687.                          case 0x18F:   /* Up Arrow */
  688.                                strcpy(buffer, "\033[A");
  689.                                return(3);
  690.                          case 0x18E:   /* Down Arrow */
  691.                                strcpy(buffer, "\033[B");
  692.                                return(3);
  693.                          case 0x18D:   /* Right Arrow */
  694.                                strcpy(buffer, "\033[C");
  695.                                return(3);
  696.                          case 0x18C:    /* Left Arrow */
  697.                                strcpy(buffer, "\033[D");
  698.                                return(3);
  699.                          case 0x18A:    /* Tab */
  700.                                strcpy(buffer, "\0x09");
  701.                                return(1);
  702.                          default:
  703.                                if (c < 0x7F)
  704.                                {
  705.                                        *buffer = c;
  706.                                        return(1);
  707.                                }
  708.                                break;
  709.                  }
  710.         }
  711.         else
  712.         {
  713.                  switch (c)
  714.                  {
  715.                          case '\r':
  716.                          case '\n':
  717.                                strcpy(buffer, "\r\n");
  718.                                return(2);
  719.                          default:
  720.                                if (c < 0x7F)
  721.                                {
  722.                                        *buffer = c;
  723.                                        return(1);
  724.                                }
  725.                                break;
  726.                  }
  727.         }
  728.  
  729.         return(0); 
  730. }
  731.  
  732. void Window_Reset(void *w)
  733. {
  734.         struct Window_Struct *Window = (struct Window_Struct *)w;
  735.         int i;
  736.  
  737.         Window->x       = 0;
  738.         Window->y       = 0;
  739.         Window->Top     = 0;
  740.         Window->Bottom  = 23;
  741.         Window->Attr    = ATTR_NORMAL;
  742.         Window->Cursor  = 1;
  743.         Window->G0      = FONT_ASCII;
  744.         Window->G1      = FONT_GRAPH;
  745.         Window->Charset = CHARSET_G0;
  746.  
  747.         Window->Parmptr = 0;
  748.         for (i = 0; i < 6; i++) Window->Parms[i] = -1;
  749.  
  750.         for (i = 0; i < SCREEN_WIDTH; i++)
  751.                 Window->Tabs[i] = (i % TAB_STOPS) ? ' ' : 'x';
  752.         Window->Tabs[SCREEN_WIDTH - 1] = 'x';
  753.  
  754.         bbc_vduq(28, 0, 23, 79, 0);
  755.  
  756.         bbc_vduq(23,96+128, 0x08,0x18,0x3C,0x7E,0x3C,0x18,0x08,0x00);
  757.         bbc_vduq(23,97+128, 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA);
  758.  
  759.         bbc_vduq(23,98+128, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  760.         bbc_vduq(23,99+128, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  761.         bbc_vduq(23,100+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  762.         bbc_vduq(23,101+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  763.  
  764.         bbc_vduq(23,102+128,0x3C,0x66,0x3C,0x00,0x00,0x00,0x00,0x00);
  765.         bbc_vduq(23,103+128,0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00);
  766.  
  767.         bbc_vduq(23,104+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  768.         bbc_vduq(23,105+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  769.  
  770.         bbc_vduq(23,106+128,0x08,0x08,0x08,0xF8,0x00,0x00,0x00,0x00);
  771.         bbc_vduq(23,107+128,0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08);
  772.         bbc_vduq(23,108+128,0x00,0x00,0x00,0x0F,0x08,0x08,0x08,0x08);
  773.         bbc_vduq(23,109+128,0x08,0x08,0x08,0x0F,0x00,0x00,0x00,0x00);
  774.         bbc_vduq(23,110+128,0x08,0x08,0x08,0xFF,0x08,0x08,0x08,0x08);
  775.         bbc_vduq(23,111+128,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  776.         bbc_vduq(23,112+128,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00);
  777.         bbc_vduq(23,113+128,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00);
  778.         bbc_vduq(23,114+128,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00);
  779.         bbc_vduq(23,115+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF);
  780.         bbc_vduq(23,116+128,0x08,0x08,0x08,0x0F,0x08,0x08,0x08,0x08);
  781.         bbc_vduq(23,117+128,0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x08);
  782.         bbc_vduq(23,118+128,0x08,0x08,0x08,0xFF,0x00,0x00,0x00,0x00);
  783.         bbc_vduq(23,119+128,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08);
  784.         bbc_vduq(23,120+128,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08);
  785.  
  786.         bbc_vduq(23,121+128,0x0C,0x18,0x30,0x60,0x30,0x18,0x7C,0x00);
  787.         bbc_vduq(23,122+128,0x30,0x18,0x0C,0x06,0x0C,0x18,0x3E,0x00);
  788.         bbc_vduq(23,123+128,0x00,0x00,0x3E,0x14,0x14,0x14,0x14,0x00);
  789.         bbc_vduq(23,124+128,0x02,0x04,0x7E,0x08,0x7E,0x20,0x40,0x00);
  790.         bbc_vduq(23,125+128,0x1C,0x36,0x30,0x7C,0x30,0x30,0x7E,0x00);
  791.         bbc_vduq(23,126+128,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00);
  792.  
  793.         bbc_vduq(23,127+128,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  794.  
  795.         bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  796.         bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  797.         bbc_cls();
  798. }
  799.  
  800. static void Window_Scroll(struct Window_Struct *Window)
  801. {
  802.         int i;
  803.  
  804.         Window->y += Window->x / 80;
  805.         Window->x %= 80;
  806.  
  807.         if (Window->y < Window->Top)
  808.         {
  809.                 for (i = 0; i < (Window->Top - Window->y); i++)
  810.                        bbc_vduq(23, 7, 0, 2, 0, 0, 0, 0, 0, 0);
  811.  
  812.                 Window->y = Window->Top;
  813.         }
  814.  
  815.         if (Window->y > Window->Bottom)
  816.         {
  817.                 for (i = 0; i < (Window->y - Window->Bottom); i++)
  818.                        bbc_vduq(23, 7, 0, 3, 0, 0, 0, 0, 0, 0);
  819.  
  820.                 Window->y = Window->Bottom;
  821.         }
  822.  
  823.         bbc_vduq(31, Window->x, Window->y);
  824. }
  825.  
  826. static os_error *Changed_Box(int Flag, change_box **Box)
  827. {
  828.         os_regset r;
  829.         os_error *e;
  830.  
  831.         r.r[0] = Flag;
  832.         e = os_swix(OS_ChangedBox, &r);
  833.         if (e == 0) *Box = (change_box *)(r.r[1]);
  834.  
  835.         return(e);
  836. }
  837.  
  838. static int keyscan(int key)
  839. {
  840.         int x, y;
  841.  
  842.         x = key ^ 0x80;
  843.  
  844.         os_byte(121, &x, &y);
  845.  
  846.         return((x == 0) ? 0 : 1);
  847. }
  848.